package cn.fintecher.pangolin.service.business.config;

import cn.fintecher.pangolin.common.enums.CaseType;
import cn.fintecher.pangolin.entity.elastic.*;
import cn.fintecher.pangolin.entity.mysql.*;
import cn.fintecher.pangolin.service.business.model.AppCardModel;
import cn.fintecher.pangolin.service.business.model.CardInfoModel;
import cn.fintecher.pangolin.service.business.model.response.*;
import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;
import org.modelmapper.PropertyMap;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Configuration
public class ModelMapperConfig {

    /**
     * 转换枚举为字符串
     */
    private static Converter<Enum, String> enumConverter = mappingContext -> {
        if (mappingContext.getSource() != null) return mappingContext.getSource().toString();
        return null;
    };

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE);

        // 机构待分配
        modelMapper.addMappings(new PropertyMap<CaseInfo, DistributedCaseResponse>() {
            @Override
            protected void configure() {
                map().setLeftAmt(source.getLeftAmt());
                map().setOverdueAmtTotal(source.getOverdueAmtTotal());
                map().setDepartmentName(source.getDepartment().getName());
            }
        });
        // 在案案件池
        modelMapper.addMappings(new PropertyMap<CaseInfo, CollectingCasesResponse>() {
            @Override
            protected void configure() {
                map().setCurrentCollecotorName(source.getCurrentCollector().getRealName());
                map().setDepartmentName(source.getCurrentCollector().getDepartment().getName());
                map().setName1(source.getCurrentCollector().getDepartment().getName());
                map().setName2(source.getDepartment().getName());
                map().setLastPayDate(source.getLatestPayDate());
            }
        });
        modelMapper.addMappings(new PropertyMap<ProcessApplication, ProcessApplicationResponse>() {
            @Override
            protected void configure() {
                map().setProcessApplicationId(source.getId());
            }
        });
        modelMapper.addMappings(new PropertyMap<HistoryCases, ReturnCasesResponse>() {
            @Override
            protected void configure() {
                map().setId(source.getId());
                map().setPrincipalName(source.getPrincipalName());
                map().setPrincipalId(source.getPrincipalId());
                map().setPersonalName(source.getPersonalName());
                map().setCertificateNo(source.getCertificateNo());
                map().setPhone(source.getPhone());
                map().setCardNo(source.getCardNo());
                map().setOverduePeriods(source.getOverduePeriods());
                map().setOverdueDays(source.getOverdueDays());
                map().setCity(source.getCity());
                map().setOverdueAmtTotal(source.getOverdueAmtTotal());
                map().setLeftAmt(source.getLeftAmt());
                map().setDelegationDate(source.getDelegationDate());
                map().setEndCaseDate(source.getEndCaseDate());
                map().setCaseNumber(source.getCaseNumber());
                map().setDeleteCaseDate(source.getDeleteCaseDate());
            }
        });
        modelMapper.addMappings(new PropertyMap<AssistCase, CaseInfoStatusResponse>() {
            @Override
            protected void configure() {
                map().setId(source.getCaseId());
                map().setLeftAmt(source.getLeftAmt());
                map().setPersonalName(source.getPersonalName());
                map().setCaseType(CaseType.TEL_CASE);
            }
        });
        modelMapper.addMappings(new PropertyMap<CaseInfo, CaseInfoStatusResponse>() {
            @Override
            protected void configure() {
                map().setCaseType(source.getCaseType());
            }
        });
        modelMapper.addMappings(new PropertyMap<BaseCase, FindRetireCaseResponse>() {
            @Override
            protected void configure() {
                map().setPersonalId(source.getId());
                map().setPersonalName(source.getPersonalName());
                map().setCaseNumber(source.getCaseNumber());
                map().setSelfPhoneNo(source.getPhone());
            }
        });
        modelMapper.addMappings(new PropertyMap<CaseInfo, FindCaseResponse>() {
            @Override
            protected void configure() {
                map().setDepartName(source.getCurrentCollector().getDepartment().getName());
                map().setCollectorName(source.getCurrentCollector().getRealName());
                map().setContactStatus(source.getContactStatus());
                map().setCollectStatus(source.getCollectStatus());
            }
        });
        modelMapper.addMappings(new PropertyMap<BaseCase, CaseInfoModelResponse>() {
            @Override
            protected void configure() {
                map().setCaseNumber(source.getCaseNumber());
                map().setBatchNumber(source.getBatchNumber());
                map().setPrincipalId(source.getPrincipalId());
                map().setPrincipalName(source.getPrincipalName());
                map().setDepartName(null);
            }
        });
        modelMapper.addMappings(new PropertyMap<BaseCase, CardInfoModel>() {
            @Override
            protected void configure() {
                map().setCaseNumber(source.getCaseNumber());
                map().setSelfPhoneNo(source.getPhone());
            }
        });
        modelMapper.addMappings(new PropertyMap<PersonalAddress, PersonalAddressResponse>() {
            @Override
            protected void configure() {
                map().setAddressDetail(source.getAddressDetail());
            }
        });
        modelMapper.addMappings(new PropertyMap<CaseInfo, LeaveCaseResponse>() {
            @Override
            protected void configure() {
                map().setCollectorName(source.getCurrentCollector().getRealName());
                map().setEndCaseDate(source.getEndCaseDate());
            }
        });

        modelMapper.addMappings(new PropertyMap<AssistCase, AssistCaseResponse>() {
            @Override
            protected void configure() {
                map().setAssistCollector(source.getAssistCollector().getRealName());
                map().setVisitTimeStart(source.getVisitTimeStart());
                map().setVisitTimeEnd(source.getVisitTimeEnd());
                map().setApplyRealName(source.getApplyRealName());
                map().setApplyReason(source.getApplyReason());
            }
        });
        modelMapper.addMappings(new PropertyMap<CaseInfo, CasePrintMessageResponse>() {
            @Override
            protected void configure() {
                map().setCaseId(source.getId());
                map().setPromiseTime(source.getPromiseDate());
                map().setPersonalName(source.getPersonalName());
                map().setOverdueDays(source.getOverdueDays());
                map().setRealPayAmount(source.getPayAmountTotal());
                map().setContractNumber(source.getCaseNumber());
                map().setContractAmount(source.getOverdueAmtTotal());
            }
        });
        modelMapper.addMappings(new PropertyMap<ProcessApprover, ProcessApproveResponse>() {
            @Override
            protected void configure() {
                map().setCaseId(source.getProcessFlowNode().getProcessApplication().getCaseId());
                map().setApplyDate(source.getProcessFlowNode().getProcessApplication().getApplyDate());
                map().setApplyName(source.getProcessFlowNode().getProcessApplication().getApplyName());
                map().setApplyRemark(source.getProcessFlowNode().getProcessApplication().getApplyRemark());
                map().setBatchNumber(source.getProcessFlowNode().getProcessApplication().getBatchNumber());
                map().setCertificateNo(source.getProcessFlowNode().getProcessApplication().getCertificateNo());
                map().setFlowType(source.getProcessFlowNode().getProcessApplication().getFlowType());
                map().setPersonalName(source.getProcessFlowNode().getProcessApplication().getPersonalName());
                map().setPrincipalName(source.getProcessFlowNode().getProcessApplication().getPrincipalName());
                map().setProcessApplicationId(source.getProcessFlowNode().getProcessApplication().getId());
                map().setProcessFlowNodeId(source.getProcessFlowNode().getId());
                map().setCaseNumber(source.getProcessFlowNode().getProcessApplication().getCaseNumber());
                map().setApprovalStatus(source.getProcessFlowNode().getApprovalStatus());
                map().setApprovedResult(source.getProcessFlowNode().getApprovedResult());
                map().setApplyContent(source.getProcessFlowNode().getProcessApplication().getApplyContent());
                map().setDerateAmount(source.getProcessFlowNode().getProcessApplication().getDerateAmount());
                map().setDerateRealAmount(source.getProcessFlowNode().getProcessApplication().getDerateRealAmount());
                map().setRemark(source.getProcessFlowNode().getRemark());
                map().setAddressDetail(source.getProcessFlowNode().getProcessApplication().getAddressDetail());
                map().setAddressType(source.getProcessFlowNode().getProcessApplication().getAddressType());
                map().setRelation(source.getProcessFlowNode().getProcessApplication().getRelation());
                map().setVisitTimeStart(source.getProcessFlowNode().getProcessApplication().getVisitTimeStart());
                map().setVisitTimeEnd(source.getProcessFlowNode().getProcessApplication().getVisitTimeEnd());
                map().setPersonalAddressId(source.getProcessFlowNode().getProcessApplication().getPersonalAddressId());
                map().setCollectorName(source.getProcessFlowNode().getProcessApplication().getCollectorName());
                map().setNodeValue(source.getProcessFlowNode().getNodeValue());
                map().setFileId(source.getProcessFlowNode().getProcessApplication().getFileId());
                map().setEndCaseDate(source.getProcessFlowNode().getProcessApplication().getEndCaseDate());
            }
        });
        modelMapper.addMappings(new PropertyMap<PaymentRecord, PaymentRecordResponse>() {
            @Override
            protected void configure() {
                map().setDepartmentName(null);
                map().setCollectorUsername(null);
            }
        });
        modelMapper.addMappings(new PropertyMap<AssistCase, FindAppCaseResponse>() {
            @Override
            protected void configure() {
                map().setId(source.getId());
//                map().setCaseId(source.getCaseId());
                map().setContactResult(source.getLastContactResult());
                map().setAssistName(source.getAssistCollector().getRealName());
                map().setVisitTimeEnd(source.getVisitTimeEnd());
                map().setCaseType(CaseType.TEL_CASE);
            }
        });

        modelMapper.addMappings(new PropertyMap<BaseCase, AppCardModel>() {
            @Override
            protected void configure() {
                map().setOpenAccountDate(source.getOpenCardDate());
                map().setStopAccountDate(source.getStopCardDate());
            }
        });
        modelMapper.addMappings(new PropertyMap<CaseInfo, FindAppCaseResponse>() {
            @Override
            protected void configure() {
                map().setId(null);
                map().setCaseId(source.getId());
                map().setFlag(0);
                map().setContactResult(source.getLastContactResult());
                map().setAssistName(source.getCurrentCollector().getRealName());
                map().setPhone(source.getPhone());
                map().setVisitTimeEnd(source.getEndCaseDate());
                map().setCaseType(source.getCaseType());
            }
        });
        return modelMapper;
    }
}
